﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IRDev.Library.ExpandedException.Factory;

namespace AutoDeploy.Common.Library
{
    /// <summary>
    /// String Helper Class 
    /// Extention Methods. 
    /// Mark Rowe markwrowe@hotmail.com  http://everythingworkflow.spaces.live.com  ,  Daniel Turnell daniel.turnell@gmail.com
    /// This Project http://autodeploy.codeplex.com
    /// </summary>
    public static class StringHelper 
    {

        /// <summary>
        /// Removes last path slash if it exists.
        /// </summary>
        /// <param name="sPath">Path String Example: C:\program files (x86)\</param>
        /// <returns>Removes any end Path Slash(\) if there is a (\) ending the string or empty string if null</returns>
        public static string RemovePathSlash(this string sPath)
        {
            List<string> Params = new List<string>();
            Params.Add(string.Format("String sPath:{0}", sPath));
            try
            {
                if (sPath == null)
                {
                    sPath = "";
                }
                if (sPath.EndsWith(@"\"))
                {
                    sPath = sPath.Substring(0, sPath.Length - 1);
                }
                return sPath;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "StringHelper", "RemovePathSlash");
                throw ee;
            }
        }
        /// <summary>
        /// ListValueMatch
        /// </summary>
        /// <param name="s">String to find</param>
        /// <param name="ls">List of string to search through</param>
        /// <param name="caseSensitive">Case sensitive</param>
        /// <returns></returns>
        public static bool ListValueMatch(this List<string> ls, string s, bool caseSensitive)
        {
            //Params
            List<string> Params = new List<string>();
            Params.Add(string.Format("String s:{0}", s));
            Params.Add(string.Format("List<String> ls:{0}", StringHelper.ListOfStringToString(ls, true)));
            Params.Add(string.Format("bool caseSensitive s:{0}", (caseSensitive ? "true" : "false")));
            try
            {
                bool isMatch = false;
                foreach (string sd in ls)
                {
                    if (!caseSensitive)
                    {
                        isMatch = (s.ToLower().Trim() == sd.ToLower().Trim());
                    }
                    else
                    {
                        isMatch = (s.Trim() == sd.Trim());
                    }
                    if (isMatch)
                    {
                        if (sd != "\n")
                        {
                            return isMatch;
                        }
                    }
                }
                return isMatch;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "StringHelper", "ListValueMatch");
                throw ee;
            }
        }
        /// <summary>
        /// ListValueContains
        /// </summary>
        /// <param name="s">String to find</param>
        /// <param name="ls">List of string to search through</param>
        /// <param name="caseSensitive">Is the search case sensitive</param>
        /// <returns>Does this List contain this value/</returns>
        public static bool ListValueContains(this List<string> ls, string s, bool caseSensitive)
        {
            //Params
            List<string> Params = new List<string>();
            Params.Add(string.Format("String s:{0}", s));
            Params.Add(string.Format("List<String> ls:{0}", StringHelper.ListOfStringToString(ls, true)));
            Params.Add(string.Format("bool caseSensitive:{0}", (caseSensitive ? "true" : "false")));
            try
            {
                bool isContained = false;
                foreach (string sd in ls)
                {
                    if (!caseSensitive)
                    {
                        isContained = s.ToLower().Contains(sd.ToLower().Trim());
                    }
                    else
                    {
                        isContained = s.Contains(sd.Trim());
                    }
                    if (isContained)
                    {
                        if (sd != "\n")
                        {
                            return isContained;
                        }
                    }
                }
                return isContained;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "StringHelper", "ListValueContains");
                throw ee;
            }
        }

        /// <summary>
        /// ListOfStringToString
        /// </summary>
        /// <param name="ls">List<string> to concatonate into a single string.</param>
        /// <param name="newLineForEachString">Create a new line for string (TODO: Change to "String Delimeter" so user can add any delimiter)</param>
        /// <returns>Return String </returns>
        public static string ListOfStringToString(this List<string> ls, bool newLineForEachString)
        {
            //Params
            List<string> Params = new List<string>();
            Params.Add(string.Format("bool newLineForEachString:{0}", (newLineForEachString ? "true" : "false")));
            try
            {
                StringBuilder sb = new StringBuilder();
                foreach (string s in ls)
                {
                    sb.Append(newLineForEachString ? s + "\n" : s);
                    Params.Add(string.Format("List<string> {0}:\n",s));
                }
                return sb.ToString();
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "StringHelper", "ListOfStringToString");
                throw ee;
            }

        }
        /// <summary>
        /// Like Split but for Strings. When you need more than a comma for a delimeter.
        /// </summary>
        /// <param name="s">String to Split into a List<string></param>
        /// <param name="delimeter">What to split on</param>
        /// <param name="trim">Trim the result strings in the List<string></param>
        /// <param name="removeEmpty">remove the empty strings int the </param>
        /// <returns>List of strings based on string List<string></returns>
        public static List<string> StringToListOfString(this string s, string delimeter, bool trim, bool removeEmpty)
        {
            //Params
            List<string> Params = new List<string>();
            Params.Add(string.Format("String s:{0}", s));
            Params.Add(string.Format("String delimeter:{0}", delimeter));
            Params.Add(string.Format("bool trim:{0}", (trim ? "true" : "false")));
            Params.Add(string.Format("bool removeEmpty:{0}", (removeEmpty ? "true" : "false")));
            List<string> ls = new List<string>();
            //My parser doesnt seem to handle escape sequences properly
            #region Special
            if (delimeter == "\n")
            {
                return s.Split('\n').ToList();
            }
            if (delimeter == "\t")
            {
                return s.Split('\t').ToList();
            }
            if (delimeter == "\r")
            {
                return s.Split('\r').ToList();
            }
            //If single char use Defualt C# Split. 
            if (delimeter.Trim().Length == 1)
            {
                return s.Split(char.Parse(delimeter[0].ToString())).ToList();
            }
            #endregion Special
            try
            {
                int IndexOfDelimeter = 0;
                int DelimeterLength = delimeter.Length;
                string Argument = "";
                string remaining = s;

                if (delimeter.Trim().Length == 0 || !s.Contains(delimeter))
                {
                    ls.Add(s);
                    return ls;
                }
                do
                {
                    IndexOfDelimeter = remaining.IndexOf(delimeter);
                    if (IndexOfDelimeter == -1)
                    {
                        ls.Add(remaining);
                        return ls;
                    }
                    else
                    {
                        if (IndexOfDelimeter < 1)
                        {
                            if (!removeEmpty)
                            {
                                ls.Add("");
                            }
                            remaining = remaining.Substring(1);
                        }
                        else
                        {
                            Argument = remaining.Substring(0, IndexOfDelimeter);
                            if (removeEmpty && Argument.Trim().Length == 0)
                            {

                            }
                            else
                            {
                                if (trim)
                                {
                                    ls.Add(Argument.Trim());
                                }
                                else
                                {
                                    ls.Add(Argument);
                                }
                            }
                            remaining = remaining.Substring(IndexOfDelimeter + DelimeterLength);
                        }
                    }
                }
                while (remaining.Length > 0);
                return ls;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "StringHelper", "StringToListOfString");
                throw ee;
            }
           
        }
        /// <summary>
        /// FormatAutoDeployValue
        /// This Formats a command to facilitate "prepared commands"
        /// </summary>
        /// <param name="s">The Command String to format</param>
        /// <param name="preparedCommands">The dictionary Key for all "prepared commands"s</param>
        /// <param name="Errors">The List of Errors that have already occured.</param>
        /// <returns>A correctly formatted string for running.</returns>
        public static string FormatAutoDeployValue(this string s, Dictionary<string,string> preparedCommands, ref List <string> Errors)
        {
            //Params
            List<string> Params = new List<string>();
            Params.Add(string.Format("String s:{0}", s));
            Params.Add(string.Format("List<string> Errors:{0}", preparedCommands));
            try
            {
                //If it has a special pre-command
                if (s.Contains("::") && s.StartsWith("["))
                {
                    List<string> ls = s.Substring(0, s.IndexOf("]")).Replace("[", "").Replace("]", "").StringToListOfString("::", true, false);
                    switch (ls[0].Trim())
                    {
                        case "PreparedApp":
                            {
                                if (preparedCommands.ContainsKey(ls[1]))
                                {
                                    s = s.Replace(s.Substring(0, s.IndexOf("]") + 1), " " + preparedCommands[ls[1]]);
                                }
                                else
                                {
                                    Errors.Add(string.Format("PreparedApp:{0} not found.\nOriginalString:{1}\n", ls[1], s));
                                    s = string.Empty;
                                }
                                break;
                            }
                    }
                }
                if (s.Contains("[Program Files]"))
                {
                    if (!ExternalHelper.CheckForFileLocation(ref s))
                    {
                        s = "File Missing";
                    }

                }

                return s;
            }
            catch (IRDev.Library.ExpandedException.Common.ExpandedException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                IRDev.Library.ExpandedException.Common.ExpandedException ee = ex.CreateAndReturnExpandedException(StringHelper.ListOfStringToString(Params, true), "StringHelper", "FormatAutoDeployValue");
                throw ee;
            }
        }
        /// <summary>
        /// Is the string able to be parsed into an int (Extention class)
        /// </summary>
        /// <param name="s">String to check</param>
        /// <returns>return true if the string is parsable.</returns>
        public static bool IsInt(this string s)
        {
            int num;
            return Int32.TryParse(s, out num);
        }


    }
}
